﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using MVCScaffold.Extensions;
using System.Data;

namespace MVCScaffold
{
    public class GerenciadorEdmx
    {
        public GerenciadorEdmx(string caminhoEdmx)
        {
            if (String.IsNullOrEmpty(caminhoEdmx))
                throw new FileNotFoundException("EDMX file not found.");

            Entidades = new List<Entity>();


            XElement xml = XElement.Load(caminhoEdmx, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
            IEnumerable<XElement> enumerable = xml.Elements();

            var xx = enumerable.Elements().Where(x => x.Name.LocalName == "ConceptualModels").First();
            DataSet dataset = new DataSet();
            dataset.ReadXml(new StringReader(xx.ToString()));

            foreach (DataTable table in dataset.Tables)
            {
                table.WriteXmlSchema("c:\\teste\\" + table.ToString() + ".xsd");
            }
            

            var conceptualModels = enumerable.Elements().Where(x => x.Name.LocalName == "ConceptualModels").First();
            CarregarTodasEntitySet(conceptualModels);
            CarregarNamespace(caminhoEdmx);
            CarregarNomeContext(conceptualModels);
            CarregarPropriedade(conceptualModels);

            var mappings = enumerable.Elements().Where(x => x.Name.LocalName == "Mappings").First();
            CarregarColumnName(mappings);


            //var storageModels = enumerable.Elements().Where(x => x.Name.LocalName == "StorageModels").First();
            //VerificarStoreGeneratedPattern(storageModels);
        }

        private void CarregarColumnName(XElement xml)
        {
            List<Property> listaPropriedades = null;
            string nome = String.Empty;
            List<string> chaves = null;

            foreach (var elementos in xml.Elements().Elements().Elements())
            {
                foreach (var mapeamento in elementos.Elements())
                {
                    foreach (var propriedade in mapeamento.Elements())
                    {


                    }
                }

                if (elementos.Name.LocalName.Equals("EntitySetMapping", StringComparison.OrdinalIgnoreCase))
                {

                }
            }
        }

        public string Namespace { get; private set; }
        public List<Entity> Entidades { get; private set; }
        public string NomeContext { get; private set; }

        private void CarregarNomeContext(XElement xml)
        {
            foreach (var item in xml.Elements().Elements())
            {
                if (item.Name.LocalName.Equals("EntityContainer", StringComparison.OrdinalIgnoreCase))
                {
                    NomeContext = item.Attribute("Name").Value;
                    break;
                }
            }
        }

        private void CarregarNamespace(string caminhoEdmx)
        {
            var arquivoDesigner = Path.Combine(Path.GetDirectoryName(caminhoEdmx), String.Format("{0}.Designer.cs", Path.GetFileNameWithoutExtension(caminhoEdmx)));
            using (StreamReader streamReader = new StreamReader(arquivoDesigner))
            {
                string conteudoArquivoDesigner = streamReader.ReadToEnd();
                var indexNamespace = conteudoArquivoDesigner.IndexOf("namespace");
                var indePrimeiraChave = conteudoArquivoDesigner.IndexOf("{");

                this.Namespace = conteudoArquivoDesigner.Substring(indexNamespace, indePrimeiraChave - indexNamespace)
                    .Replace("namespace", "").Trim();
            }
        }

        private void CarregarTodasEntitySet(XElement xml)
        {
            foreach (var item in xml.Elements().Elements())
            {
                if (item.Name.LocalName.Equals("EntityContainer", StringComparison.OrdinalIgnoreCase))
                {
                    foreach (var entitySet in item.Elements().Where(x => x.Name.LocalName == "EntitySet").Select(x => x.Attribute("Name")))
                        this.Entidades.Add(new Entity() { Name = entitySet.Value, IsSelected = true });
                }
            }
        }

        private void CarregarPropriedade(XElement xml)
        {
            List<Property> listaPropriedades = null;
            string nome = String.Empty;
            List<string> chaves = null;

            foreach (var elementos in xml.Elements().Elements())
            {
                if (elementos.Name.LocalName.Equals("EntityType", StringComparison.OrdinalIgnoreCase))
                {
                    listaPropriedades = new List<Property>();
                    nome = elementos.Attribute("Name").Value;

                    chaves = elementos.Elements()
                        .Where(x => x.Name.LocalName == "Key").Elements()
                        .Select(key => key.Attribute("Name").Value).ToList();

                    foreach (var property in elementos.Elements().Where(x => x.Name.LocalName == "Property"))
                    {
                        var item = new Property()
                                              {
                                                  Name = property.Attribute("Name").Value,
                                                  Type = Type.GetType(String.Format("System.{0}", property.Attribute("Type").Value)),
                                                  IsKey = chaves.Where(x => x == property.Attribute("Name").Value).Count() > 0
                                              };

                        listaPropriedades.Add(item);
                    }

                    var propriedade = Entidades.FirstOrDefault(x => x.Name == nome);
                    propriedade.Properties = listaPropriedades;
                }
            }
        }

        private void VerificarStoreGeneratedPattern(XElement xml)
        {
            List<Property> listaPropriedades = null;
            string nome = String.Empty;
            List<string> chaves = null;

            foreach (var elementos in xml.Elements().Elements())
            {
                if (elementos.Name.LocalName.Equals("EntityType", StringComparison.OrdinalIgnoreCase))
                {
                    listaPropriedades = new List<Property>();
                    nome = elementos.Attribute("Name").Value;

                    chaves = elementos.Elements()
                        .Where(x => x.Name.LocalName == "Key").Elements()
                        .Select(key => key.Attribute("Name").Value).ToList();

                    foreach (var property in elementos.Elements().Where(x => x.Name.LocalName == "Property"))
                    {
                        var item = new Property()
                        {
                            Name = property.Attribute("Name").Value,
                            Type = Type.GetType(String.Format("System.{0}", property.Attribute("Type").Value)),
                            IsKey = chaves.Where(x => x == property.Attribute("Name").Value).Count() > 0
                        };

                        listaPropriedades.Add(item);
                    }

                    var propriedade = Entidades.FirstOrDefault(x => x.Name == nome);
                    propriedade.Properties = listaPropriedades;
                }
            }
        }
    }
}
